package org.projects.graduates.domain;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.projects.graduates.page.Pager;

import com.dayatang.domain.AbstractEntity;
import com.dayatang.domain.QuerySettings;

@Entity
@Table(name = "teachings")
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Teaching extends AbstractEntity {
	private static final long serialVersionUID = -4612045359511806349L;
	
	//谁教
	@OneToOne
	@NotNull
	private Person person;
	//课程的关联
	@OneToOne
	@NotNull
	private Course course;

	// 课程登记时间
	@Temporal(TemporalType.DATE)
	@Column(name = "set_up_date")
	private Date setUpDate;

	// 星数
	private int star;

	//与重复的关联
	@OneToOne
	private Repeat repeat;

	private final static String QL = "select count(o.id) from org.projects.graduates.domain.Teaching o ";

	public void setUp(Person person, Course course) {
		this.person = person;
		this.course = course;
		this.setUpDate = new Date();
		this.save();
	}

	// ***************
	// / 这个方法需要重构
	// ***************
	public static List<Course> findBy(Person person) {
		List<Course> results = new ArrayList<Course>();

		QuerySettings<Teaching> settings = QuerySettings.create(Teaching.class);
		settings.eq("person", person);
		for (Teaching t : getRepository().find(settings)) {
			results.add(t.getCourse());
		}

		return results;
	}

	public static Teaching findBy(Course course) {
		QuerySettings<Teaching> settings = QuerySettings.create(Teaching.class);
		settings.eq("course", course);
		return getRepository().getSingleResult(settings);
	}

	public static List<Teaching> teachesOf(Person person) {
		List<Teaching> results = new ArrayList<Teaching>();
		results.addAll(getRepository().find(QuerySettings.create(Teaching.class).eq("person", person)));
		return results;
	}

	/**
	 * 按最新来排序
	 * 
	 * @return
	 */
	public static List<Teaching> theLasts(long currentPage, long pageSize, Person except) {
		List<Teaching> results = new ArrayList<Teaching>();
		QuerySettings<Teaching> settings = QuerySettings.create(Teaching.class).desc("id");
		if (except != null) {
			settings.notEq("person", except);
		}

		settings.notIn("course", Studying.allCourseOf(except));

		Pager pager = pagerOfAll(currentPage, pageSize);
		settings.setFirstResult(Integer.parseInt("" + pager.startLine()));
		settings.setMaxResults(Integer.parseInt("" + pageSize));
		results.addAll(getRepository().find(settings));
		return results;
	}

	public static List<Teaching> theLasts(int currentPage, int pageSize) {
		return theLasts(currentPage, pageSize, null);
	}

	// 本人的最新在教课程
	public static List<Teaching> thePersonalLasts(long personId) {
		List<Teaching> results = new ArrayList<Teaching>();
		QuerySettings<Teaching> settings = QuerySettings.create(Teaching.class);
		settings.eq("person.id", personId).desc("id");
		results.addAll(getRepository().find(settings));
		return results;
	}

	public static List<Teaching> thePersonalLasts(long personId, long currentPage, long pageSize) {
		List<Teaching> results = new ArrayList<Teaching>();
		QuerySettings<Teaching> settings = QuerySettings.create(Teaching.class);
		Pager pager = countOfPersons(personId, currentPage, pageSize);
		settings.setFirstResult(Integer.parseInt("" + pager.startLine()));
		settings.setMaxResults(Integer.parseInt("" + pageSize));
		settings.eq("person.id", personId).desc("id");
		results.addAll(getRepository().find(settings));
		return results;
	}

	public static Pager pagerOfAll(long currentPage, long pageSize) {
		return new Pager(count(" order by o.id desc "), pageSize, currentPage);
	}

	public static Pager pagerOfAll(long personId, long currentPage, long pageSize) {
		return new Pager(count("where o.person.id <> " + personId + " order by o.id desc "), pageSize, currentPage);
	}

	public static Pager countOfPersons(long personId, long currentPage, long pageSize) {
		return new Pager(count(" where o.person.id = " + personId), pageSize, currentPage);
	}

	public static long count(String query) {
		String ql = QL + query;
		Map<String, Object> params = new HashMap<String, Object>();
		List<Long> count = new ArrayList(getRepository().find(ql, params));
		return null == count ? 0 : count.get(0).intValue();
	}

	public Teaching() {
		super();
	}

	public boolean equals(Object other) {
		if (null == other) {
			return false;
		}
		if (other instanceof Teaching) {
			Teaching o = (Teaching) other;
			if (o.getId() == this.getId()) {
				return true;
			}
		}
		return false;
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder(17, 37).append(this.getId()).toHashCode();
	}

	@Override
	public String toString() {
		return person.getShowName() + " teach " + course.getName();
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Course getCourse() {
		return course;
	}

	public void setCourse(Course course) {
		this.course = course;
	}

	public Date getSetUpDate() {
		return setUpDate;
	}

	public void setSetUpDate(Date setUpDate) {
		this.setUpDate = setUpDate;
	}

	public int getStar() {
		return star;
	}

	public void setStar(int star) {
		this.star = star;
	}

	public Repeat getRepeat() {
		return repeat;
	}

	public void setRepeat(Repeat repeat) {
		this.repeat = repeat;
	}

}
